package com.example.myapplication;

import android.Manifest;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.StrictMode;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.RuntimePermissions;

import static java.lang.String.valueOf;

@RuntimePermissions
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private Camera camera;
    private SurfaceHolder holder;
    private boolean isBefore = false;

    private Button bt_start;
    private Button bt_end;
    private Button bt_timing;
    private Button bt_change;
    private SurfaceView surfaceView;

    private String outputAddr;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_start = findViewById(R.id.bt_start);
        bt_end = findViewById(R.id.bt_end);
        bt_timing = findViewById(R.id.bt_timing);
        bt_change = findViewById(R.id.bt_change);
        surfaceView = findViewById(R.id.surfaceView);
        initPhotoError();
        holder = surfaceView.getHolder();
        //添加监听回调
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        initCamera();
        bt_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MainActivityPermissionsDispatcher.cameraWithCheck(MainActivity.this);//调用此方法即可动态申请权限；

            }
        });
        bt_end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stop();
            }
        });

        bt_timing.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                timing();
            }


        });

        bt_change.setOnClickListener(new View.OnClickListener() {


            @Override
            public void onClick(View view) {
                isBefore = !isBefore;
                if (camera != null) {
                    camera.stopPreview();//停掉原来摄像头的预览
                    camera.release();//释放资源
                    camera = null;//取消原来摄像头
                }
                int CammeraIndex;

                if (isBefore) {
                    CammeraIndex = FindFrontCamera();
                } else {
                    CammeraIndex = FindBackCamera();
                }
                camera = Camera.open(CammeraIndex);
                try {
                    camera.setDisplayOrientation(90);
                    camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
                    Camera.Parameters parameters = camera.getParameters();
                    camera.setParameters(parameters);
                    camera.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 10s 开始录制，10 结束上传
     */
    private void timing() {
        ToastUtil.showToast(MainActivity.this, "10s后开始录制视频");
        new CountDownTimer(10000, 1000) {
            public void onTick(long millisUntilFinished) {
                //ToastUtil.showToast(MainActivity.this, "seconds remaining: " + millisUntilFinished / 1000);
            }

            public void onFinish() {
                ToastUtil.showToast(MainActivity.this, "开始录制视频");
                MainActivityPermissionsDispatcher.cameraWithCheck(MainActivity.this);//调用此方法即可动态申请权限；
                new CountDownTimer(10000 + 1000, 1000) {
                    public void onTick(long millisUntilFinished) {
                    }

                    public void onFinish() {
                        ToastUtil.showToast(MainActivity.this, "结束录制视频");
                        stop();
                    }
                }.start();


            }
        }.start();

    }

    private int FindFrontCamera() {
        int cameraCount = 0;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras(); // get cameras number

        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                // 代表摄像头的方位，目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
                return camIdx;
            }
        }
        return -1;
    }

    private int FindBackCamera() {
        int cameraCount = 0;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras(); // get cameras number

        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                // 代表摄像头的方位，目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
                return camIdx;
            }
        }
        return -1;
    }

    MediaRecorder recorder;

    @NeedsPermission({Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})
    public void camera() {
        startRecorder();
//                Camera.startPreview()
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void initPhotoError() {
        // android 7.0系统解决拍照的问题
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        builder.detectFileUriExposure();
    }

    private void startRecorder() {
        initCamera();
        CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        recorder = new MediaRecorder();
        recorder.setCamera(camera);
        recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        //3st. config
//        recorder.setOutputFormat(mProfile.fileFormat);
//        recorder.setAudioEncoder(mProfile.audioCodec);
//        recorder.setVideoEncoder(mProfile.videoCodec);
//        recorder.setOutputFile("/sdcard/FBVideo.3gp");
//        recorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
//        recorder.setVideoFrameRate(mProfile.videoFrameRate);
//        recorder.setVideoEncodingBitRate(mProfile.videoBitRate);
        recorder.setAudioEncodingBitRate(mProfile.audioBitRate);
        recorder.setAudioChannels(mProfile.audioChannels);
        recorder.setOrientationHint(90);
        recorder.setAudioSamplingRate(mProfile.audioSampleRate);
        recorder.setPreviewDisplay(holder.getSurface());


        // Step 3: Set a Camera Parameters
        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        /* Fixed video Size: 640 * 480*/
        recorder.setVideoSize(640, 480);
        /* Encoding bit rate: 1 * 1024 * 1024*/
        recorder.setVideoEncodingBitRate(1 * 1024 * 1024);
        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//        recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
        // 设置输出格式
//        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        // 这两项需要放在setOutputFormat之后
//        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//声音编码格式
//        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//视频编码格式

        outputAddr = getVideoSavePath();
        recorder.setOutputFile(outputAddr);
        try {
            recorder.prepare();
            recorder.start();
        } catch (IOException e) {
            Log.d("----------", "startRecorder: " + e.getMessage());
            e.printStackTrace();
        }

    }

    /**
     * 停止录制
     */
    private void stop() {
        recorder.stop();
        recorder.reset();
        recorder.release();
        recorder = null;
        Log.d("----------", "stopRecorder: " + outputAddr);

        String uploadUrl = "http://39.106.141.187:18080/upload/uploadVideo";

        File file = new File(outputAddr);
        postFile(uploadUrl, null, file);


    }

    protected void postFile(final String url, final Map<String, Object> map, File file) {
        OkHttpClient client = new OkHttpClient();
        // form 表单形式上传
        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
        if (file != null) {
            // MediaType.parse() 里面是上传的文件类型。
            RequestBody body = RequestBody.create(MediaType.parse("video/*"), file);
            String filename = file.getName();
            // 参数分别为， 请求key ，文件名称 ， RequestBody
            requestBody.addFormDataPart("file", file.getName(), body);
        }
        if (map != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry entry : map.entrySet()) {
                requestBody.addFormDataPart(valueOf(entry.getKey()), valueOf(entry.getValue()));
            }
        }
        Request request = new Request.Builder().url(url).post(requestBody.build()).build();
        // readTimeout("请求超时时间" , 时间单位);
        client.newBuilder().readTimeout(500000, TimeUnit.MILLISECONDS).build().newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i("----------", e.getMessage());
                ToastUtil.showToast(MainActivity.this, e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String str = response.body().string();
                    Log.i("----------", response.message() + " , body " + str);
                    ToastUtil.showToast(MainActivity.this, str);


                } else {
                    Log.i("----------", response.message() + " error : body " + response.body().string());
                }
            }
        });

    }


    /**
     * 加载相机配置
     */
    private void initCamera() {
        try {
            camera = Camera.open();
            //对焦
            Camera.Parameters cameraParams = camera.getParameters();
            // set the focus mode
            cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            // set Camera parameters
            camera.setParameters(cameraParams);

            camera.setPreviewDisplay(holder);//当前控件显示相机数据
            camera.setDisplayOrientation(90);//调整预览角度
            camera.unlock();
            camera.startPreview();
        } catch (Exception e) {
//            releaseCamera()
        }

    }

    /**
     * 释放相机
     */
    private void releaseCamera() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }

    /**
     * 获取视频保存路径
     */
    private String getVideoSavePath() {
        return Environment.getExternalStorageDirectory().getPath() + File.separator + "vedio-" + UUID.randomUUID() + ".mp4";
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        camera.open();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        initCamera();
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        releaseCamera();
    }
}
